﻿//**********************************************************
//Copyright(C)2010 By 波特商网公司 版权所有。
//
//文件名：
//文件功能：ucTextBoxButton自定义控件
//
//创建标识： 米海波 || 2011-07-07
//
//修改标识：
//修改描述：
//**********************************************************
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace Hmc.IM.Common.UserControls
{
    public partial class ucTextBoxButton : UserControl, IValidate
    {

        /// <summary>
        /// 是否打开下拉
        /// </summary>
        private bool _dropdown = false;

        private int _maxItemNumber = 10;

        /// <summary>
        /// 最大行
        /// </summary>
        public int MaxItemNumber
        {
            get { return _maxItemNumber; }
            set { _maxItemNumber = value; }
        }

        private object _dataSourse;

        /// <summary>
        /// 绑定的数据源
        /// </summary>
        public object DataSourse
        {
            get { return _dataSourse; }
            set
            {
                _dataSourse = value;
                dgvGrid.DataSource = value;
            }
        }

        private string _displayMember;

        /// <summary>
        /// 用于绑定显示的字段名称
        /// </summary>
        public string DisplayMember
        {
            get { return _displayMember; }
            set 
            { 
                _displayMember = value;
                colKey.DataPropertyName = value;
            }
        }
        private string _valueMember;

        /// <summary>
        /// 用于取值的字段名称
        /// </summary>
        public string ValueMember
        {
            get { return _valueMember; }
            set 
            { 
                _valueMember = value;
                colValue.DataPropertyName = value;
            }
        }

        /// <summary>
        /// 获取显示的文本
        /// </summary>
        public string SelectedText
        {
            get { return txtMessage.Text; }
            set
            {
                txtMessage.Text = value;
                txtMessage.Select(value.Length, 0);
            }
        }

        /// <summary>
        /// 获取显示的文本
        /// </summary>
        public override string Text
        {
            get
            {
                return txtMessage.Text; ;
            }
            set
            {
                txtMessage.Text = value;
                txtMessage.Select(value.Length, 0);
            }
        }

        private object _selectedValue;

        /// <summary>
        /// 当前选择的值
        /// </summary>
        public object SelectedValue
        {
            get { return _selectedValue; }
            set
            {
                _selectedValue = value;
            }
        }

        /// <summary>
        /// 当前选择的绑定对象
        /// </summary>
        public object SelectedItem
        {
            get;
            set;
        }


        private string defultTips = "输入查询信息！";

        /// <summary>
        /// 默认提示文本
        /// </summary>
        public string DefultTips
        {
            get { return defultTips; }
            set { defultTips = value; }
        }

        /// <summary>
        /// 是否允许为空
        /// </summary>
        public bool IsAllowEmpty
        {
            get { return txtMessage.IsAllowEmpty; }
            set { txtMessage.IsAllowEmpty = value; }
        }

        /// <summary>
        /// 错误显示
        /// </summary>
        ucErrorProvider error = new ucErrorProvider();

        /// <summary>
        /// 选择数据行执行事件
        /// </summary>
        public event EventHandler<UserEventArgs> Selected;

        /// <summary>
        /// 点击查询时出发
        /// </summary>
        public event EventHandler<QueryEventArgs> DoSearch;

        /// <summary>
        /// 初始化构造界面基本组件
        /// </summary>
        public ucTextBoxButton()
        {
            InitializeComponent();
            button.MouseLeave += new EventHandler(button_MouseLeave);
            button.MouseDown += new MouseEventHandler(button_MouseDown);
            button.MouseUp += new MouseEventHandler(button_MouseUp);
            button.Click += new EventHandler(button_Click);
            txtMessage.KeyPress += new KeyPressEventHandler(txtMessage_KeyPress);
            plDetails.Paint += new PaintEventHandler(plDetails_Paint);
            dgvGrid.RowTemplate.Height = 21;
            LayoutControls();
            this.Disposed += new EventHandler(ucTextBoxButton_Disposed);
            this.Leave += new EventHandler(item_Leave);
            foreach (Control item in this.Controls)
            {
                item.Leave += new EventHandler(item_Leave);
            }
        }

        void item_Leave(object sender, EventArgs e)
        {
            //Application.DoEvents();
            bool focused = GetChildFocused(this);
            bool plfocused = GetChildFocused(plDetails);
            if (!focused&& !plfocused && this._dropdown)
            {
                button_Click(null, new EventArgs());
            }
        }

        private bool GetChildFocused(Control ctr)
        {
            if (ctr.Focused) return true;
            foreach (Control item in ctr.Controls)
            {
                if (item.Focused)
                {
                    return true;
                }
                else if (item.Controls.Count > 0)
                {
                    if (GetChildFocused(item))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 释放如下控件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ucTextBoxButton_Disposed(object sender, EventArgs e)
        {
            error.Dispose();
            dgvGrid.Dispose();
            button.Dispose();
            txtMessage.Dispose();
            txtSearch.Dispose();
            pbSearch.Dispose();
            plDetails.Dispose();
        }

        void plDetails_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawRectangle(new Pen(Color.FromArgb(129, 127, 130)), plDetails.DisplayRectangle.X, plDetails.DisplayRectangle.Y, plDetails.DisplayRectangle.Width - 1, plDetails.DisplayRectangle.Height - 1);
            e.Graphics.Dispose();
        }

        void button_Click(object sender, EventArgs e)
        {
            if (sender != null)
            {
                txtMessage.Focus();
            }
            if (!this.Enabled) return;
            if (this._dropdown)
            {
                plDetails.Visible = false;
                this._dropdown = false;
            }
            else
            {
                ShowDropDown();
            }
        }

        #region 按钮事件

        /// <summary>
        /// 鼠标松开按键
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void button_MouseUp(object sender, MouseEventArgs e)
        {
            Label btn = sender as Label;
            btn.Image.Dispose();
            btn.Image = Properties.Resources.btn1;
        }

        /// <summary>
        /// 鼠标按下按键
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void button_MouseDown(object sender, MouseEventArgs e)
        {
            Label btn = sender as Label;
            btn.Image.Dispose();
            btn.Image = Properties.Resources.btn2;
        }

        /// <summary>
        /// 鼠标离开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void button_MouseLeave(object sender, EventArgs e)
        {
            Label btn = sender as Label;
            btn.Image.Dispose();
            btn.Image = Properties.Resources.btn1;
        }

        #endregion

        /// <summary>
        /// 只处理删除键
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void txtMessage_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)8)   //退格键
            {
                txtMessage.Clear();
                this.SelectedValue = null;
                this.SelectedItem = null;
                if (Selected != null)
                {
                    Selected(this, new UserEventArgs());
                }
            }
            else
            {
                if (!this._dropdown)
                {
                    ShowDropDown();
                    txtSearch.Focus();
                }
                e.Handled = true;
            }
            
        }

        private void txtSearch_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)//回车
            {
                pbSearch_Click(pbSearch, new EventArgs());
                e.Handled = true;
            }
        }

        private void txtSearch_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Down)
            {
                if (dgvGrid.Rows.Count > 0)
                    dgvGrid.Focus();
            }
        }

        /// <summary>
        /// 布局
        /// </summary>
        private void LayoutControls()
        {
            this.txtMessage.Location = new Point(0, 0);
            this.txtMessage.Width = this.Width;
            this.Height = this.txtMessage.Height;
            txtSearch.Location = new Point(1, 1);
            txtSearch.Width = plDetails.Width - 2;
            dgvGrid.Location = new Point(1, txtSearch.Height);
            dgvGrid.Width = plDetails.Width -2;
            dgvGrid.Height = plDetails.Height - txtSearch.Height - 2;

            pbSearch.Location = new Point(txtSearch.Width - pbSearch.Width - 2, txtSearch.Location.Y);
            pbSearch.Parent = txtSearch;
            pbSearch.BringToFront();

            
            button.TextAlign = ContentAlignment.BottomCenter;
            button.Height = txtMessage.Height - 2;
            button.Location = new Point(txtMessage.Width - button.Width - 1, txtMessage.Location.Y + 1);
            button.Parent = txtMessage;
            button.BringToFront();
        }
                
        /// <summary>
        /// 显示下拉列表
        /// </summary>
        private void ShowDropDown()
        {
            if (this.Parent == null)
                return;
            Point pos = new Point(this.Left, this.Bottom - 1);

            Point parentPos = this.Parent.PointToScreen(this.Parent.Location);
            Point topParentPos = this.TopLevelControl.PointToScreen(this.Parent.Location);
            pos.Offset(parentPos.X - topParentPos.X, parentPos.Y - topParentPos.Y);
            if ((pos.Y + this.plDetails.Height) > this.TopLevelControl.ClientRectangle.Height)
            {
                pos.Y -= (this.Height + this.plDetails.Height);
                if (pos.Y < 0)
                {
                    pos.Y = (this.TopLevelControl.ClientRectangle.Height - this.plDetails.Height);
                }
            }

            // 尝试停靠,如果右边超过顶级窗口的客户区，则将控件向左移动，并紧靠在顶级窗口右侧
            if ((pos.X + this.plDetails.Width) > this.TopLevelControl.ClientRectangle.Width)
                pos.X = (this.TopLevelControl.ClientRectangle.Width - this.plDetails.Width);

            this.plDetails.Location = pos;// this.Parent.PointToScreen(pt);
            this.plDetails.Parent = this.TopLevelControl;
            this.plDetails.BringToFront();
            this.plDetails.Visible = true;
            this._dropdown = true;
        }

        private void pbSearch_Click(object sender, EventArgs e)
        {
            if (DoSearch != null)
            {
                string query = txtSearch.Text.Trim() == this.defultTips ? string.Empty : txtSearch.Text;
                DoSearch(this, new QueryEventArgs() { Query = query});
            }
        }

        /// <summary>
        /// 根据大小自动调整
        /// </summary>
        /// <param name="e"></param>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            LayoutControls();
        }

        /// <summary>
        /// 加载控件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            plDetails.Visible = false;
        }

        private void dgvGrid_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if ((e.RowIndex > -1))
            {
                object tag = dgvGrid.Rows[e.RowIndex].DataBoundItem;
                this.SelectedText = dgvGrid.Rows[e.RowIndex].Cells[colKey.Index].Value.ToString();
                this.SelectedItem = tag;
                this.SelectedValue = dgvGrid.Rows[e.RowIndex].Cells[colValue.Index].Value;
                button_Click(button, new EventArgs());
                if (Selected != null)
                {
                    Selected(this, new UserEventArgs() { UserTag = tag });
                }
            }
        }

        /// <summary>
        /// 启用禁用
        /// </summary>
        /// <param name="e"></param>
        protected override void OnEnabledChanged(EventArgs e)
        {
            base.OnEnabledChanged(e);
            txtMessage.Enabled = this.Enabled;
            button.Enabled = this.Enabled;
        }

        /// <summary>
        /// 执行验证
        /// </summary>
        /// <returns></returns>
        public new bool Validate()
        {
            this.IsValidated = false;
            error.Clear();
            if (!IsAllowEmpty && txtMessage.Text.Trim() == string.Empty)
            {
                error.SetError(this, "该项不能为空！");
            }
            else if ((this.Expression != null) && (this.Expression != string.Empty) && !Regex.IsMatch(txtMessage.Text,this.Expression))
            {
                error.SetError(this, this.SetError);
            }
            else
            {
                this.IsValidated = true;
            }
            return this.IsValidated;
        }

        /// <summary>
        /// 是否通过验证
        /// </summary>
        public bool IsValidated
        {
            get;
            set;
        }

        /// <summary>
        /// 正则验证
        /// </summary>
        public string Expression
        {
            get;
            set;
        }

        /// <summary>
        /// 错误提示
        /// </summary>
        public string SetError
        {
            get;
            set;
        }

        /// <summary>
        /// 处理按键
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dgvGrid_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                if (dgvGrid.CurrentRow != null)
                {
                    object tag = dgvGrid.CurrentRow.DataBoundItem;
                    this.SelectedText = dgvGrid.CurrentRow.Cells[colKey.Index].Value.ToString();
                    this.SelectedItem = tag;
                    this.SelectedValue = dgvGrid.CurrentRow.Cells[colValue.Index].Value;
                    button_Click(button, new EventArgs());
                    if (Selected != null)
                    {
                        Selected(this, new UserEventArgs() { UserTag = tag });
                    }
                    e.Handled = true;
                }
            }
        }
    }

    /// <summary>
    /// 用户选择数据事件信息
    /// </summary>
    public class UserEventArgs : EventArgs
    {
        /// <summary>
        /// 选择的用户数据
        /// </summary>
        public object UserTag { get; set; }
    }

    /// <summary>
    /// 查询数据
    /// </summary>
    public class QueryEventArgs : EventArgs
    {
        /// <summary>
        /// 查询内容
        /// </summary>
        public string Query { get; set; }
    }
}
